﻿using System;
using SD.LLBLGen.Pro.ORMSupportClasses;
using SD.LLBLGen.Pro.QuerySpec;
using SD.LLBLGen.Pro.QuerySpec.Adapter;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VNet.VisiSuite.Dal.DatabaseSpecific;
using VNet.VisiSuite.Dal.EntityClasses;
using VNet.VisiSuite.Dal.FactoryClasses;
using VNet.VisiSuite.Dal.HelperClasses;
using VNet.VisiSuite.Service.Contact.Message.Base;
using VNet.VisiSuite.Service.Contact.Message.Item;
using VNet.VisiSuite.BusinessLogic.BusinessException;
using VNet.VisiSuite.Common.Logger;
using VNet.VisiSuite.Common.Resource;
using VNet.VisiSuite.Common.Helper;
using VNet.VisiSuite.Service.Contact.Message;

namespace VNet.VisiSuite.BusinessLogic
{
    public class CellUtil
    {
        private QueryFactory _queryFactory = new QueryFactory();

        public SaveDataResponse<CellItem> UpdateCell(SaveDataRequest<CellItem> request)
        {
            using (var adapter = new DataAccessAdapter())
            {
                try
                {
                    var errorMessage = string.Empty;
                    if (!string.IsNullOrEmpty(errorMessage = CheckCellNameUnique(adapter, request.Data)))
                        return new SaveDataResponse<CellItem> { Success = false, Error = new ServiceError { Description = errorMessage, }, };

                    var cellQuery = _queryFactory.Cell.Where(CellFields.CellId == request.Data.CellId);
                    var cellEntity = adapter.FetchFirst(cellQuery);
                    if (cellEntity == null)
                        return new SaveDataResponse<CellItem> { Success = false, Error = BusinessLogicError.CellDoesNotExist };

                    cellEntity.LastUpdatedBy = request.Identity.UserLoginId;
                    cellEntity.LastUpdatedDate = DateTime.UtcNow;
                    cellEntity.CellName = request.Data.CellName;
                    cellEntity.Description = request.Data.Description;
                    cellEntity.Enabled = request.Data.Enabled;
                    cellEntity.VisiCentralGroup = request.Data.VisiCentralGroup;
                    cellEntity.VisiCentralRow = request.Data.VisiCentralRow;
                    cellEntity.VisiCentralColumn = request.Data.VisiCentralColumn;

                    if (!string.IsNullOrWhiteSpace(request.Data.Password))
                        cellEntity.Password = EncryptionHelper.EncodePassword(request.Data.Password);

                    if (!adapter.SaveEntity(cellEntity))
                        return new SaveDataResponse<CellItem> { Success = false, Error = BusinessLogicError.UpdateCellFailed };

                    // Get cell entity after updated
                    var q = _queryFactory.Create()
                        .Select(() => new
                        {
                            AreaId = CellFields.AreaId.Source("c").ToValue<int>(),
                            Password = CellFields.Password.Source("c").ToValue<string>(),
                            Description = CellFields.Description.Source("c").ToValue<string>(),
                            Enabled = CellFields.Enabled.Source("c").ToValue<Boolean>(),
                            CellName = CellFields.CellName.Source("c").ToValue<string>(),
                            VisiCentralGroup = CellFields.VisiCentralGroup.Source("c").ToValue<byte>(),
                            VisiCentralRow = CellFields.VisiCentralRow.Source("c").ToValue<byte>(),
                            VisiCentralColumn = CellFields.VisiCentralColumn.Source("c").ToValue<byte>(),
                            LastUpdatedDate = CellFields.LastUpdatedDate.Source("c").ToValue<DateTime>(),
                            CellId = CellFields.CellId.Source("c").ToValue<int>(),
                            FirstName1 = (UserLoginFields.FirstName.Source("u").SetFieldAlias("FistName1")).ToValue<string>(),
                            LastName1 = (UserLoginFields.LastName.Source("u").SetFieldAlias("LastName1")).ToValue<string>(),
                        })
                        .From(_queryFactory.Cell.As("c").InnerJoin(CellEntity.Relations.UserLoginEntityUsingLastUpdatedBy, "c", "u"))
                        .Where(CellFields.CellId.Source("c") == request.Data.CellId);

                    var val = adapter.FetchQuery(q).FirstOrDefault();
                    if (val == null)
                        return new SaveDataResponse<CellItem> { Success = false, Error = BusinessLogicError.UpdateCellFailed };

                    return new SaveDataResponse<CellItem>
                    {
                        Success = true,
                        Data = new CellItem
                        {
                            CellId = val.CellId,
                            AreaId = val.AreaId,
                            //Password = val.Password,
                            Description = val.Description,
                            CellName = val.CellName,
                            Enabled = val.Enabled,
                            VisiCentralGroup = val.VisiCentralGroup,
                            VisiCentralRow = val.VisiCentralRow,
                            VisiCentralColumn = val.VisiCentralColumn,
                            LastUpdatedBy = string.Format(FormatString.NameFormat, val.FirstName1, val.LastName1),
                            LastUpdatedDate = val.LastUpdatedDate,
                        }
                    };
                }
                catch (Exception ex)
                {
                    FileLog.Error("UpdateCell", ex);
                    return new SaveDataResponse<CellItem> { Success = false, Error = BusinessLogicError.UpdateCellFailed };
                }
            }


        }

        public SaveDataResponse<CellItem> InsertCell(SaveDataRequest<CellItem> request)
        {
            using (var adapter = new DataAccessAdapter())
            {
                try
                {
                    //Check overlap
                    string errorMessage = null;
                    if (!string.IsNullOrEmpty(errorMessage = CheckCellNameUnique(adapter, request.Data)))
                        return new SaveDataResponse<CellItem> { Success = false, Error = new ServiceError { Description = errorMessage, }, };

                    var cellEntity = new CellEntity();
                    var now = DateTime.UtcNow;
                    cellEntity.AreaId = request.Data.AreaId;
                    cellEntity.Description = request.Data.Description;
                    cellEntity.CellName = request.Data.CellName;
                    cellEntity.Enabled = request.Data.Enabled;
                    cellEntity.Operators = 1;
                    cellEntity.VisiCentralGroup = request.Data.VisiCentralGroup;
                    cellEntity.VisiCentralRow = request.Data.VisiCentralRow;
                    cellEntity.VisiCentralColumn = request.Data.VisiCentralColumn;
                    cellEntity.CreatedDate = now;
                    cellEntity.CreatedBy = request.Identity.UserLoginId;
                    cellEntity.LastUpdatedDate = now;
                    cellEntity.LastUpdatedBy = request.Identity.UserLoginId;

                    if (!string.IsNullOrWhiteSpace(request.Data.Password))
                        cellEntity.Password = EncryptionHelper.EncodePassword(request.Data.Password);

                    if (!adapter.SaveEntity(cellEntity, true))
                        return new SaveDataResponse<CellItem> { Success = false, Error = BusinessLogicError.InsertCellFailed };

                    // Get cell entity after updated
                    var q = _queryFactory.Create()
                        .Select(() => new
                        {
                            AreaId = CellFields.AreaId.Source("c").ToValue<int>(),
                            Description = CellFields.Description.Source("c").ToValue<string>(),
                            Password = CellFields.Password.Source("c").ToValue<string>(),
                            CellName = CellFields.CellName.Source("c").ToValue<string>(),
                            Enabled = CellFields.Enabled.Source("c").ToValue<Boolean>(),
                            VisiCentralGroup = CellFields.VisiCentralGroup.Source("c").ToValue<byte>(),
                            VisiCentralRow = CellFields.VisiCentralRow.Source("c").ToValue<byte>(),
                            VisiCentralColumn = CellFields.VisiCentralColumn.Source("c").ToValue<byte>(),
                            LastUpdatedDate = CellFields.LastUpdatedDate.Source("c").ToValue<DateTime>(),
                            CellId = CellFields.CellId.Source("c").ToValue<int>(),
                            FirstName1 = (UserLoginFields.FirstName.Source("u").SetFieldAlias("FistName1")).ToValue<string>(),
                            LastName1 = (UserLoginFields.LastName.Source("u").SetFieldAlias("LastName1")).ToValue<string>(),
                        })
                        .From(_queryFactory.Cell.As("c").InnerJoin(CellEntity.Relations.UserLoginEntityUsingLastUpdatedBy, "c", "u"))
                        .Where(CellFields.CellId.Source("c") == cellEntity.CellId);

                    var val = adapter.FetchQuery(q).FirstOrDefault();
                    if (val == null)
                        return new SaveDataResponse<CellItem> { Success = false, Error = BusinessLogicError.InsertCellFailed };

                    return new SaveDataResponse<CellItem>
                    {
                        Success = true,
                        Data = new CellItem
                        {
                            CellId = val.CellId,
                            AreaId = val.AreaId,
                            //Password = val.Password,
                            Description = val.Description,
                            CellName = val.CellName,
                            Enabled = val.Enabled,
                            VisiCentralGroup = val.VisiCentralGroup,
                            VisiCentralRow = val.VisiCentralRow,
                            VisiCentralColumn = val.VisiCentralColumn,
                            CreatedBy = string.Format(FormatString.NameFormat, val.FirstName1, val.LastName1),
                            CreatedDate = val.LastUpdatedDate,
                            LastUpdatedBy = string.Format(FormatString.NameFormat, val.FirstName1, val.LastName1),
                            LastUpdatedDate = val.LastUpdatedDate,
                        }
                    };
                }
                catch (Exception ex)
                {
                    FileLog.Error("InsertCell", ex);
                    return new SaveDataResponse<CellItem> { Success = false, Error = BusinessLogicError.InsertCellFailed };
                }
            }
        }

        public DeleteDataResponse DeleteCell(DeleteDataRequest request)
        {
            using (var adapter = new DataAccessAdapter())
            {
                try
                {
                    var query = _queryFactory.Create()
                                         .Select(CellShiftFields.CellShiftId)
                                         .From(_queryFactory.CellShift)
                                         .Where(CellShiftFields.CellId == request.DataId);

                    var dataTable = adapter.FetchAsDataTable(query);
                    if (dataTable == null)
                        return new DeleteDataResponse { Success = false, Error = BusinessLogicError.DeleteCellFailed };

                    if (dataTable.Rows.Count > 0)
                        return new DeleteDataResponse { Success = false, Error = new ServiceError { Description = string.Format(FormatString.CannotDeleteItem2, "cell") }, };

                    var query2 = _queryFactory.Cell.Where(CellFields.CellId == request.DataId);
                    var cellEntity = adapter.FetchFirst(query2);
                    if (cellEntity == null)
                        return new DeleteDataResponse { Error = BusinessLogicError.CellDoesNotExist, Success = false };

                    if (!adapter.DeleteEntity(cellEntity))
                        return new DeleteDataResponse { Error = BusinessLogicError.DeleteCellFailed, Success = false };

                    return new DeleteDataResponse { Success = true, DataId = request.DataId };
                }
                catch
                {
                    return new DeleteDataResponse { Success = false, Error = BusinessLogicError.DeleteCellFailed };
                }
            }
        }

        private string CheckCellNameUnique(DataAccessAdapter adapter, CellItem data)
        {
            var query = _queryFactory.Cell.Where(CellFields.Enabled == true & CellFields.CellName == data.CellName
                                               & CellFields.AreaId == data.AreaId & CellFields.CellId != data.CellId);
            var cells = (EntityCollection<CellEntity>)adapter.FetchQuery(query);

            if (cells != null && cells.Count > 0)
                return ErrorMessages.ExistedCellName;
            return null;
        }

        #region Cells for VisiCentral

        public GetDataResponse<IList<CellItem>> GetCells(GetDataRequest request)
        {
            using (var adapter = new DataAccessAdapter())
            {
                try
                {
                    var qf = new QueryFactory();
                    var qry = qf.Cell.WithPath(CellEntity.PrefetchPathUserLogin, CellEntity.PrefetchPathUserLogin1)
                        .Where(CellFields.AreaId == request.Id)
                        .OrderBy(CellFields.VisiCentralGroup.Ascending())
                        .OrderBy(CellFields.VisiCentralRow.Ascending())
                        .OrderBy(CellFields.VisiCentralColumn.Ascending());

                    var cells = (EntityCollection<CellEntity>)adapter.FetchQuery(qry);
                    if (cells == null)
                        return new GetDataResponse<IList<CellItem>> { Success = false, Error = BusinessLogicError.GetReasonCodeFailed };

                    var list = new List<CellItem>();
                    foreach (var entity in cells)
                    {
                        var ci = new CellItem
                        {
                            CellId = entity.CellId,
                            AreaId = entity.AreaId,
                            //Password = val.Password,
                            Description = entity.Description,
                            CellName = entity.CellName,
                            Enabled = entity.Enabled,
                            VisiCentralGroup = entity.VisiCentralGroup ?? 0,
                            VisiCentralRow = entity.VisiCentralRow ?? 0,
                            VisiCentralColumn = entity.VisiCentralColumn ?? 0,
                            CreatedBy = entity.UserLogin != null ? string.Format("{0} {1}", entity.UserLogin.FirstName, entity.UserLogin.LastName) : string.Empty,
                            LastUpdatedBy = entity.UserLogin1 != null ? string.Format("{0} {1}", entity.UserLogin1.FirstName, entity.UserLogin1.LastName) : string.Empty,
                            CreatedDate = entity.LastUpdatedDate,
                            LastUpdatedDate = entity.LastUpdatedDate,
                        };

                        list.Add(ci);
                    }
                    return new GetDataResponse<IList<CellItem>> { Success = true, Data = list };
                }
                catch (Exception ex)
                {
                    FileLog.Error("GetCells", ex);
                    return new GetDataResponse<IList<CellItem>> { Success = false, Error = BusinessLogicError.GetReasonCodeFailed };
                }
            }
        }

        #endregion
    }
}
